package com.ning.parking.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ning.parking.config.GlobalVariableUtils;
import com.ning.parking.domain.ParkingLotBaseInfo;
import com.ning.parking.domain.VO.Pagination;
import com.ning.parking.domain.dto.ParkingLotBaseInfoAddOrUpdateDTO;
import com.ning.parking.domain.dto.ParkingLotBaseInfoDto;
import com.ning.parking.domain.dto.ParkingSpaceDTO;
import com.ning.parking.domain.dto.SysUserParkingLotSaveDTO;
import com.ning.parking.mapper.ParkingLotBaseInfoMapper;
import com.ning.parking.service.ParkingLotBaseInfoService;
import com.ning.parking.service.ParkingLotDrivewayInfoService;
import com.ning.parking.service.SysUserFeignClient;
import com.scsonic.common.domain.parklot.ParkingLotBaseInfoVO;
import com.scsonic.common.enums.parking.ParkingStatusEnum;
import com.scsonic.common.enums.parklot.CodeSuffixEnum;
import com.scsonic.common.enums.parklot.ParkingLotConfigStatusEnum;
import com.scsonic.common.enums.parklot.ParkingLotContactSourceTypeEnum;
import com.scsonic.framework.common.response.R;
import com.scsonic.framework.exception.BizException;
import com.scsonic.framework.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DecimalFormat;
import java.util.List;
import java.util.Objects;


/**
 *
 */
@Slf4j
@Service
public class ParkingLotBaseInfoServiceImpl extends ServiceImpl<ParkingLotBaseInfoMapper, ParkingLotBaseInfo>
        implements ParkingLotBaseInfoService {

    @Autowired
    private ParkingLotDrivewayInfoService parkingLotDrivewayInfoService;
    @Autowired
    private SysUserFeignClient sysUserFeignClient;
    @Autowired
    private ParkingLotConfigProcessService parkingLotConfigProcessService;

    @Override
    public ParkingLotBaseInfo saveParkingLotBaseInfo(ParkingLotBaseInfo parkingLotBaseInfo) {
        DateTime date = DateUtils.date();
        parkingLotBaseInfo.setParkingLotCode("P"+date.getTime());
        parkingLotBaseInfo.setUpdateTime(date);
        parkingLotBaseInfo.setUpdateBy(GlobalVariableUtils.getUser().getUserName());
        parkingLotBaseInfo.setCreateBy(GlobalVariableUtils.getUser().getUserName());
        parkingLotBaseInfo.setCreateTime(date);
        save(parkingLotBaseInfo);

        if (ObjectUtil.isNotEmpty(parkingLotBaseInfo.getParkingLotDrivewayInfos())){
            parkingLotDrivewayInfoService.saveBatch(parkingLotBaseInfo.getParkingLotDrivewayInfos());
        }
        return parkingLotBaseInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ParkingLotBaseInfoVO save(ParkingLotBaseInfoAddOrUpdateDTO parkingLotBaseInfoDTO) {
        if(isRepeatParkingLotByName(parkingLotBaseInfoDTO.getParkingLotName(), null)) {
            throw new BizException("停车场名称【" + parkingLotBaseInfoDTO.getParkingLotName() + "】已存在");
        }

        // 校验车位数限制
        carPlacesCheck(BeanUtil.toBean(parkingLotBaseInfoDTO, CarPlacesCheckDTO.class));

        ParkingLotBaseInfo entity = BeanUtil.copyProperties(parkingLotBaseInfoDTO, ParkingLotBaseInfo.class);

        // 默认自动生成停车场编码
        if (StringUtils.isBlank(parkingLotBaseInfoDTO.getParkingLotCode())) {
            entity.setParkingLotCode(baseMapper.countParkingLotContainDel() + 1);

            entity.setParkingLotCode(getParkingLotCodeByRule(parkingLotBaseInfoDTO.getCountyCode(), entity.getParkingLotCode()));
        }
//        entity.setSpecialParkingLotCode(entity.getParkingLotCode());
        entity.setConfigStatus(ParkingLotConfigStatusEnum.UNDONE);
        entity.setEmptyPlaces(Objects.isNull(entity.getEmptyPlaces()) ? entity.getTotalPlaces() : entity.getEmptyPlaces());
        baseMapper.insert(entity);

        // 更新联系人信息表
       // parkingLotContactInfoService.update(entity.getParkingLotId(), null, ParkingLotContactSourceTypeEnum.PARKING_LOT_BASE_INFO);
        // 记录停车场配置的流程步骤
        parkingLotConfigProcessService.saveOrUpdateParkingLotConfig(entity.getParkingLotId(), ConfigStepEnum.BASE_INFO_CONFIG, ParkingLotConfigStatusEnum.FINISH);
        // 记录停车场的区域配置流程步骤
        parkingLotConfigProcessService.saveOrUpdateAreaConfig(entity.getParkingLotId(), ParkingLotConfigStatusEnum.UNDONE);
        entity = getById(entity.getParkingLotId());
        ParkingLotBaseInfoVO baseInfoVO = BeanUtil.copyProperties(entity, ParkingLotBaseInfoVO.class);
        SysUserParkingLotSaveDTO parkingLotSaveDTO = SysUserParkingLotSaveDTO.builder()
                .orgId(entity.getOrgId())
                .parkingLotId(entity.getParkingLotId())
                .build();
        // 变更了机构，需要更新用户权限
        R<Void> response = sysUserFeignClient.saveUserParkingLot(parkingLotSaveDTO);
        if (!response.isSuccess()) {
            throw new BizException("更新机构下用户的停车场权限失败");
        }
        return baseInfoVO;
    }

    /**
     * 根据规则生成一个停车场编码
     * 停车场唯一编码，规则为 P+行政区编码+顺序号(00001)，每增加一个停车场顺序号+1  + 00000 + 0
     *
     * @return 停车场编码
     */
    public String getParkingLotCodeByRule(String areaCode, String codeNum) {
        // 顺序号
        DecimalFormat decimalFormat = new DecimalFormat("00000");
        return "P" + areaCode + decimalFormat.format(codeNum) + "00000" + CodeSuffixEnum.PARKING_LOT.getValue();
    }

    @Override
    public Pagination<ParkingLotBaseInfo> parkingLotBasePage(ParkingLotBaseInfoDto parkingLotBaseInfoDto) {
        Page<ParkingLotBaseInfo> page = lambdaQuery()
                .like(ObjectUtil.isNotEmpty(parkingLotBaseInfoDto.getParkingLotName()),ParkingLotBaseInfo::getParkingLotName, parkingLotBaseInfoDto.getParkingLotName())
                .orderByDesc(ParkingLotBaseInfo::getUpdateTime).page(parkingLotBaseInfoDto.toPage());
        return Pagination.of(page);
    }

    @Override
    public void exitSpace(Long parkingLotId) {
        try {
            ParkingSpaceDTO parkingSpaceDTO = new ParkingSpaceDTO();
            parkingSpaceDTO.setParentParkingLotId(parkingLotId);
            parkingSpaceDTO.setParkingLotId(parkingLotId);
            parkingSpaceDTO.setParkingStatus(ParkingStatusEnum.LEAVE);
            this.baseMapper.updateEmptySpace(parkingSpaceDTO);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void entSpace(Long parkingLotId) {
        try {
            ParkingSpaceDTO parkingSpaceDTO = new ParkingSpaceDTO();
            parkingSpaceDTO.setParentParkingLotId(parkingLotId);
            parkingSpaceDTO.setParkingLotId(parkingLotId);
            parkingSpaceDTO.setParkingStatus(ParkingStatusEnum.IN_PARKING);
            this.baseMapper.updateEmptySpace(parkingSpaceDTO);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private boolean isRepeatParkingLotByName(String parkingLotName, Object o) {
        List<ParkingLotBaseInfo> list = lambdaQuery().eq(ParkingLotBaseInfo::getParkingLotName, parkingLotName).list();
        return ObjectUtil.isEmpty(list)?false:true;
    }

    /**
     * 车位数校验
     *
     * @param carPlacesCheckDTO 参数
     */
    private void carPlacesCheck(CarPlacesCheckDTO carPlacesCheckDTO) {
        int carPlaces = carPlacesCheckDTO.getTemPlaces() + carPlacesCheckDTO.getMonthlyPlaces() + carPlacesCheckDTO.getNewEnergyPlaces() + carPlacesCheckDTO.getAppointPlaces() + carPlacesCheckDTO.getAccessiblePlaces();
        if (carPlaces > carPlacesCheckDTO.getTotalPlaces()) {
            throw new BizException("分类车位总数不可以大于总车位数");
        }
        if (carPlacesCheckDTO.getEmptyPlaces() > carPlacesCheckDTO.getTotalPlaces()) {
            throw new BizException("剩余车位数不可以大于总车位数");
        }
    }

}

